package controllers

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"strings"
	"time"
)

type BusRep struct {
	List     []GzStagesInfo `json:"list"`
	Stations []Stations     `json:"stations"`
}

type GzStagesInfo struct {
	StageId   string `json:"stageId"`
	StageName string `json:"stageName"`
}

type Stations struct {
	BusStation BusStation `json:"busStation"`
	Entryname  string     `json:"entryname"`
	Entrys     []Entrys   `json:"entrys"`
}

type BusStation struct {
	Busstationname string `json:"busstationname"`
	Namecn         string `json:"namecn"`
}

type Entrys struct {
	TempBusName string       `json:"tempBusName"`
	Entryname   string       `json:"entryname"`
	Resources   []BusStation `json:"resources"`
}

func GzStages() map[string]string {
	resp, err := http.Get("http://cs.gzmtr.com/clkweb/doLoadLinesAndStations.do")
	if err != nil {
		log.Fatalf("Get TencentMapSite init error:% s", err.Error())
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Println("TencentMapSite body error:", err)
	}

	// log.Println(string(data))
	temp := strings.Replace(string(data), "null(", "", -1)
	new := temp[0 : len(temp)-1]
	// log.Println(new)

	var obj BusRep
	if err := json.Unmarshal([]byte(new), &obj); err != nil {
		log.Println("json to struct error:", err)
		// log.Println("json to struct error:", err)
	}

	// log.Println("obj to struct:", obj)

	busIndex := make(map[string]string)
	for _, value := range obj.List {
		busIndex[value.StageName] = value.StageId
	}
	// log.Println("obj to struct:", busIndex)

	return busIndex
}

func GzBus(stageId string) map[string]EntrysRes {
	resp, err := http.Get(fmt.Sprintf("http://cs.gzmtr.com/clkweb/doBusTransfer.do?stageId=%s", stageId))
	if err != nil {
		log.Fatalf("Get TencentMapSite init error:% s", err.Error())
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Println("GzBus body error:", err)
	}

	// log.Println(string(data))
	temp := strings.Replace(string(data), "null(", "", -1)
	new := temp[0 : len(temp)-1]
	// log.Println(new)

	var obj BusRep
	if err := json.Unmarshal([]byte(new), &obj); err != nil {
		log.Println("json to struct error:", err)
		// log.Println("json to struct error:", err)
	}

	busmap := make(map[string]EntrysRes)
	for _, bus := range obj.Stations {
		var busStages BusStages
		busStages.Name = bus.BusStation.Busstationname
		for _, busname := range bus.Entrys {
			busStages.Bus = append(busStages.Bus, busname.TempBusName)
		}
		if old, ok := busmap[bus.Entryname]; ok {
			old.BusStages = append(old.BusStages, busStages)
			busmap[bus.Entryname] = old
		} else {
			var new EntrysRes
			new.BusStages = append(new.BusStages, busStages)
			busmap[bus.Entryname] = new
		}
	}
	// log.Println("obj to struct:", obj)
	return busmap
}

func GzDoor(key string) []Entrys {
	// http://cs.gzmtr.com/base/doSearchEntryAndResource.do?station=%25E8%25A5%25BF%25E6%259C%2597
	time.Sleep(time.Second)
	value := url.Values{}
	value.Set("station", url.QueryEscape(key))
	ask := value.Encode()
	// ask = "station=%25E8%25A5%25BF%25E6%259C%2597"
	// log.Println("ask", ask)
	resp, err := http.Get(fmt.Sprintf("http://cs.gzmtr.com/base/doSearchEntryAndResource.do?%s", ask))
	if err != nil {
		log.Fatalf("Get TencentMapSite init error:% s", err.Error())
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Println("GzBus body error:", err)
	}

	// log.Println(string(data))
	temp := strings.Replace(string(data), "null(", "", -1)
	new := temp[0 : len(temp)-1]
	// log.Println(new)

	// CreateFile("./demo/GzDoor.json", []byte(new))
	var obj Stations
	if err := json.Unmarshal([]byte(new), &obj); err != nil {
		log.Println("json to struct error:", key, err, new)
		// log.Println("json to struct error:", err)
		time.Sleep(time.Second)
		return GzDoor(key)
	}

	// log.Println("obj to struct:", obj.Entrys)
	return obj.Entrys
}

func GzDeal() {
	// metro := ReadJsonFile("./data/guangzhou.json").(Metro)
	var metro Metro
	ReadJsonFileToStruct("./data/guangzhou.json", &metro)
	stageIndex := GzStages()
	for linekey, line := range metro.LineData {
		if line.LineName == "有轨电车" {
			break
		}
		for stagekey, stage := range line.Stages {
			if strings.Contains(stage.Name, "（") {
				stage.Name = strings.Split(stage.Name, "（")[0]
			}
			if v, ok := stageIndex[stage.Name]; ok {
				// log.Println("stage name:", linekey, stagekey, stage.Name)
				busIndex := GzBus(v)
				doorlist := GzDoor(stage.Name)
				var entrysResList []EntrysRes
				for _, door := range doorlist {
					var entrysRes EntrysRes
					entrysRes.EntryName = door.Entryname
					for _, res := range door.Resources {
						entrysRes.Res = append(entrysRes.Res, res.Namecn)
					}
					entrysRes.BusStages = busIndex[door.Entryname].BusStages
					entrysResList = append(entrysResList, entrysRes)
				}
				metro.LineData[linekey].Stages[stagekey].EntrysRes = entrysResList
			} else {
				log.Println("Can not find stage. name:", stage.Name)
			}
		}
	}
	obj, _ := json.Marshal(metro)
	CreateFile("./data/guangzhou3.json", obj)
}
